local Aloft = Aloft
if not Aloft then return end
local AloftModules = AloftModules
if not AloftModules then return end

-----------------------------------------------------------------------------

local version, build, date, tocversion = GetBuildInfo()

--[[
	nameplateShowFriends = { text = "UNIT_NAMEPLATES_SHOW_FRIENDS" },
	nameplateShowFriendlyPets = { text = "UNIT_NAMEPLATES_SHOW_FRIENDLY_PETS" },
	nameplateShowFriendlyGuardians = { text = "UNIT_NAMEPLATES_SHOW_FRIENDLY_GUARDIANS" },
	nameplateShowFriendlyTotems = { text = "UNIT_NAMEPLATES_SHOW_FRIENDLY_TOTEMS" },
	nameplateShowEnemies = { text = "UNIT_NAMEPLATES_SHOW_ENEMIES" },
	nameplateShowEnemyPets = { text = "UNIT_NAMEPLATES_SHOW_ENEMY_PETS" },
	nameplateShowEnemyGuardians = { text = "UNIT_NAMEPLATES_SHOW_ENEMY_GUARDIANS" },
	nameplateShowEnemyTotems = { text = "UNIT_NAMEPLATES_SHOW_ENEMY_TOTEMS" },
	nameplateAllowOverlap = { text = "UNIT_NAMEPLATES_ALLOW_OVERLAP" },
]]

AloftModules:AddInitializer("AloftAutoShow", function()

-----------------------------------------------------------------------------

local AloftAutoShow = Aloft:NewModule("AutoShow", Aloft, "AceEvent-3.0", "AceHook-3.0", "AceTimer-3.0")
AloftAutoShow.dynamic = "AloftAutoShow"

-----------------------------------------------------------------------------

AloftAutoShow.namespace = "autoShow"
AloftAutoShow.defaults =
{
	profile =
	{
		bounceOverlap	= false,

		allOverlap		= false,
		allEnemyEnable	= true,
		allFriendEnable	= false,

		overlap =
		{
			state =
			{
				combat			= false,
				flagged			= false,
				group			= false,
				resting			= false,
				default			= false,
			},
			place =
			{
				world			= false,
				battleground	= false,
				arena			= false,
				party			= false,
				raid			= false,
			},
		},

		friendly =
		{
			state =
			{
				combat			= false,
				flagged			= false,
				group			= false,
				resting			= false,
				default			= false,
			},
			place =
			{
				world			= false,
				battleground	= false,
				arena			= false,
				party			= false,
				raid			= false,
			},
		},
		friendlyPet =
		{
			state =
			{
				combat			= false,
				flagged			= false,
				group			= false,
				resting			= false,
				default			= false,
			},
			place =
			{
				world			= false,
				battleground	= false,
				arena			= false,
				party			= false,
				raid			= false,
			},
		},
		friendlyGuardian =
		{
			state =
			{
				combat			= false,
				flagged			= false,
				group			= false,
				resting			= false,
				default			= false,
			},
			place =
			{
				world			= false,
				battleground	= false,
				arena			= false,
				party			= false,
				raid			= false,
			},
		},
		friendlyTotem =
		{
			state =
			{
				combat			= false,
				flagged			= false,
				group			= false,
				resting			= false,
				default			= false,
			},
			place =
			{
				world			= false,
				battleground	= false,
				arena			= false,
				party			= false,
				raid			= false,
			},
		},

		enemy =
		{
			state =
			{
				combat			= true,
				flagged			= true,
				group			= true,
				resting			= true,
				default			= true,
			},
			place =
			{
				world			= true,
				battleground	= true,
				arena			= true,
				party			= true,
				raid			= true,
			},
		},
		enemyPet =
		{
			state =
			{
				combat			= true,
				flagged			= true,
				group			= true,
				resting			= true,
				default			= true,
			},
			place =
			{
				world			= true,
				battleground	= true,
				arena			= true,
				party			= true,
				raid			= true,
			},
		},
		enemyGuardian =
		{
			state =
			{
				combat			= true,
				flagged			= true,
				group			= true,
				resting			= true,
				default			= true,
			},
			place =
			{
				world			= true,
				battleground	= true,
				arena			= true,
				party			= true,
				raid			= true,
			},
		},
		enemyTotem =
		{
			state =
			{
				combat			= true,
				flagged			= true,
				group			= true,
				resting			= true,
				default			= true,
			},
			place =
			{
				world			= true,
				battleground	= true,
				arena			= true,
				party			= true,
				raid			= true,
			},
		},
	},
}

-----------------------------------------------------------------------------

local IsInInstance = IsInInstance
local IsResting = IsResting
local GetNumPartyMembers = GetNumPartyMembers
local GetNumRaidMembers = GetNumRaidMembers
local UnitAffectingCombat = UnitAffectingCombat
local UnitIsPVP = UnitIsPVP
local UnitIsPVPFreeForAll = UnitIsPVPFreeForAll

local unpack = unpack

-----------------------------------------------------------------------------

function AloftAutoShow:OnInitialize()
	if self.db ~= Aloft.AloftDB:GetNamespace(self.namespace, true) then self.db = Aloft.AloftDB:RegisterNamespace(self.namespace, self.defaults) end
end

function AloftAutoShow:OnEnable()
	self:RegisterEvents()
	self:HookNameplates()

	-- turn namplates on/off based on current state
	-- ChatFrame7:AddMessage("AloftAutoShow:OnEnable(): " .. tostring(self.db) .. "/" .. tostring(self.db and self.db.profile) .. "/" .. tostring(self.db and self.db.profile and self.db.profile.friendlyTotem))
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnDisable()
	self:UnregisterAllEvents()
	self:UnregisterAllMessages()
	self:CancelAllTimers()

	self:UnhookAll()
end

-----------------------------------------------------------------------------

function AloftAutoShow:RegisterEvents()
	self:UnregisterAllEvents()
	self:UnregisterAllMessages()
	self:CancelAllTimers()

	self:RegisterEvent("PLAYER_REGEN_DISABLED", "OnPlayerRegenDisabled")
	self:RegisterEvent("PLAYER_REGEN_ENABLED", "OnPlayerRegenEnabled")
	self:RegisterEvent("PLAYER_UPDATE_RESTING", "OnPlayerUpdateResting")
	self:RegisterEvent("RAID_ROSTER_UPDATE", "OnRaidRosterUpdate")
	self:RegisterEvent("PARTY_MEMBERS_CHANGED", "OnPartyMembersChanged")
	-- self:RegisterEvent("ARENA_TEAM_ROSTER_UPDATE", "OnArenaTeamRosterUpdate") -- TODO: determine if this is even needed; this fires repeatedly when things change; don't know what to do about it
	self:RegisterEvent("PLAYER_ENTERING_WORLD", "OnPlayerEnteringWorld")
	self:RegisterEvent("ZONE_CHANGED_NEW_AREA","OnPlayerEnteringWorld")
end

function AloftAutoShow:HookNameplates()
	self:UnhookAll()

	-- ChatFrame7:AddMessage("AloftAutoShow:HookNameplates(): enter")
	self:Hook(Aloft, "SetEnemyNameplateDisplay")
	self:Hook(Aloft, "SetFriendNameplateDisplay")
end

-----------------------------------------------------------------------------

function AloftAutoShow:OnPlayerRegenDisabled(event)
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnPlayerRegenEnabled(event)
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnPlayerUpdateResting(event)
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnRaidRosterUpdate(event)
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnPartyMembersChanged(event)
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnArenaTeamRosterUpdate(event)
	self:ApplyNameplateDisplay()
end

function AloftAutoShow:OnPlayerEnteringWorld(event)
	self:ApplyNameplateDisplay()
end

-----------------------------------------------------------------------------

function AloftAutoShow:GetEnemyNameplateDisplay()
	return self:GetNameplateConfig(self.db.profile.enemy)
end

function AloftAutoShow:SetEnemyNameplateDisplay(this, value)
	-- ChatFrame7:AddMessage("AloftAutoShow:SetEnemyNameplateDisplay(): " .. tostring(version) .. "/" .. tostring(tocversion))
	if self.db.profile.allEnemyEnable then
		-- ChatFrame7:AddMessage("AloftAutoShow:SetEnemyNameplateDisplay(): " .. tostring(value))
		self:SetAllEnemyNameplateDisplay(value)
	else
		self:SetNameplateConfig(self.db.profile.enemy, value)
	end

	self:ApplyAllNameplateConfig()
end

function AloftAutoShow:SetAllEnemyNameplateDisplay(value)
	-- ChatFrame7:AddMessage("AloftAutoShow:SetAllEnemyNameplateDisplay(): " .. tostring(version) .. "/" .. tostring(tocversion))
	self:SetAllNameplateConfig(self.db.profile.enemyTotem, value)
	self:SetAllNameplateConfig(self.db.profile.enemyGuardian, value)
	self:SetAllNameplateConfig(self.db.profile.enemyPet, value)

	self:SetAllNameplateConfig(self.db.profile.enemy, value)
end

function AloftAutoShow:GetFriendNameplateDisplay()
	return self:GetNameplateConfig(self.db.profile.friendly)
end

-----------------------------------------------------------------------------

function AloftAutoShow:SetFriendNameplateDisplay(this, value)
	-- ChatFrame7:AddMessage("AloftAutoShow:SetFriendNameplateDisplay(): " .. tostring(version) .. "/" .. tostring(tocversion))
	if self.db.profile.allFriendEnable then
		-- ChatFrame7:AddMessage("AloftAutoShow:SetFriendNameplateDisplay(): " .. tostring(value))
		self:SetAllFriendNameplateDisplay(value)
	else
		self:SetNameplateConfig(self.db.profile.friendly, value)
	end

	self:ApplyAllNameplateConfig()
end

function AloftAutoShow:SetAllFriendNameplateDisplay(value)
	-- ChatFrame7:AddMessage("AloftAutoShow:SetAllFriendNameplateDisplay(): " .. tostring(version) .. "/" .. tostring(tocversion))
	self:SetAllNameplateConfig(self.db.profile.friendlyTotem, value)
	self:SetAllNameplateConfig(self.db.profile.friendlyGuardian, value)
	self:SetAllNameplateConfig(self.db.profile.friendlyPet, value)

	self:SetAllNameplateConfig(self.db.profile.friendly, value)
end

-----------------------------------------------------------------------------

function AloftAutoShow:SetAllNameplateOverlap(value)
	-- ChatFrame7:AddMessage("AloftAutoShow:SetAllNameplateOverlap(): " .. tostring(version) .. "/" .. tostring(tocversion))
	self:SetAllNameplateConfig(self.db.profile.overlap, value)
end

-----------------------------------------------------------------------------

function AloftAutoShow:GetNameplateConfig(data)
	if not data then return nil end

	local stateValue = nil
	if UnitAffectingCombat("player") then
		stateValue = data.state.combat
	elseif UnitIsPVP("player") or UnitIsPVPFreeForAll("player") then
		stateValue = data.state.flagged
	elseif IsResting() then
		stateValue = data.state.resting
	elseif (GetNumPartyMembers() > 0)  or (GetNumRaidMembers() > 0) then
		stateValue = data.state.group
	else
		stateValue = data.state.default
	end

	local placeValue
	local inInstance, instanceType = IsInInstance()
	if inInstance and instanceType ~= "none"then
		if instanceType == "pvp" then
			placeValue = data.place.battleground
		elseif instanceType == "arena" then
			placeValue = data.place.arena
		elseif instanceType == "party" then
			placeValue = data.place.party
		elseif instanceType == "raid" then
			placeValue = data.place.raid
		else
			placeValue = data.place.world
		end
	else
		placeValue = data.place.world
	end

	return stateValue and placeValue
end

function AloftAutoShow:SetNameplateConfig(data, value)
	if not data then return nil end

	if UnitAffectingCombat("player") then
		data.state.combat = value
	elseif UnitIsPVP("player") or UnitIsPVPFreeForAll("player") then
		data.state.flagged = value
	elseif IsResting() then
		data.state.resting = value
	elseif (GetNumPartyMembers() > 0)  or (GetNumRaidMembers() > 0) then
		data.state.group = value
	else
		data.state.default = value
	end

	local inInstance, instanceType = IsInInstance()
	if inInstance and instanceType ~= "none"then
		if instanceType == "pvp" then
			data.place.battleground = value
		elseif instanceType == "arena" then
			data.place.arena = value
		elseif instanceType == "party" then
			data.place.party = value
		elseif instanceType == "raid" then
			data.place.raid = value
		else
			data.place.world = value
		end
	else
		data.place.world = value
	end
end

function AloftAutoShow:SetAllNameplateConfig(data, value)
	if not data then return nil end

	data.state.combat = value
	data.state.flagged = value
	data.state.resting = value
	data.state.group = value
	data.state.default = value

	data.place.battleground = value
	data.place.arena = value
	data.place.party = value
	data.place.raid = value
	data.place.world = value
end

-----------------------------------------------------------------------------

function AloftAutoShow:ApplyNameplateDisplay()
	-- ChatFrame7:AddMessage("AloftAutoShow:ApplyNameplateDisplay(): " .. tostring(self.db) .. "/" .. tostring(self.db and self.db.profile) .. "/" .. tostring(self.db and self.db.profile and self.db.profile.friendlyTotem))
	self:ApplyAllNameplateConfig()
end

function AloftAutoShow:ApplyNameplateConfig(cVar, data)
	Aloft:SetNameplateCVar(cVar, self:GetNameplateConfig(data))
end

function AloftAutoShow:ApplyAllNameplateConfig()
	-- ChatFrame7:AddMessage("AloftAutoShow:ApplyAllNameplateConfig(): " .. tostring(version) .. "/" .. tostring(tocversion))
	-- ChatFrame7:AddMessage("AloftAutoShow:ApplyAllNameplateConfig(): " .. tostring(self.db) .. "/" .. tostring(self.db and self.db.profile) .. "/" .. tostring(self.db and self.db.profile and self.db.profile.friendlyTotem))

	self:ApplyNameplateConfig("nameplateShowFriendlyTotems", self.db.profile.friendlyTotem)
	self:ApplyNameplateConfig("nameplateShowFriendlyGuardians", self.db.profile.friendlyGuardian)
	self:ApplyNameplateConfig("nameplateShowFriendlyPets", self.db.profile.friendlyPet)

	self:ApplyNameplateConfig("nameplateShowFriends", self.db.profile.friendly)

	self:ApplyNameplateConfig("nameplateShowEnemyTotems", self.db.profile.enemyTotem)
	self:ApplyNameplateConfig("nameplateShowEnemyGuardians", self.db.profile.enemyGuardian)
	self:ApplyNameplateConfig("nameplateShowEnemyPets", self.db.profile.enemyPet)

	self:ApplyNameplateConfig("nameplateShowEnemies", self.db.profile.enemy)

	local previousOverlap = self.db.profile.bounceOverlap and Aloft:GetNameplateCVar("nameplateAllowOverlap")
	self:ApplyNameplateConfig("nameplateAllowOverlap", self.db.profile.overlap)

	if self.db.profile.bounceOverlap and previousOverlap ~= Aloft:GetNameplateCVar("nameplateAllowOverlap") then
		-- ChatFrame7:AddMessage("AloftAutoShow:ApplyAllNameplateConfig(): bounce")
		Aloft:BounceEnemyNameplates()
		Aloft:BounceFriendNameplates()
	end
end

-----------------------------------------------------------------------------

end)
